﻿using System;
using nRoute.Components.Composition;
using Orktane.Components;
using Orktane.ScriptActionModel;

namespace Orktane.ScriptActions
{
    [MapScriptAction("HELP", "Help", ShortDescription = "Provides help information for available commands.",
        Lifetime = InstanceLifetime.PerInstance, UnListed = true)]
    public class HelpScriptAction
        : IConsoleScriptAction
    {
        private const string HELP_MOREINFO = "For more information on a specific command, type HELP command-name";
        private const string HELP_MOREONLINE = "For more information on any command, please seek online documentation.";
        private const string ECLIPSE = "...";
        private const string SPACE = " ";

        private IConsole _console;
        private IDisposable _completionToken;

#region I_consoleScriptAction Members

        public void Intialize(IConsole console, IDisposable completionToken)
        {
            if (console == null) throw new ArgumentNullException("console");
            if (completionToken == null) throw new ArgumentNullException("completionToken");

            _console = console;
            _completionToken = completionToken;
        }

        public bool Cancel() 
        {
            return true;
        }

        public void Close() { }

#endregion

#region IScriptAction Members

        public void Execute(Arguments args)
        {
            // we write the args
            if (args != null && !string.IsNullOrEmpty(args.CommandLine))
            {
                // todo: implement help for individual 
                _console.WriteLine("HELP ON INDIVIDUAL SCRIPT ACTIONS IS NOT AVAILABLE.");
            }
            else
            {
                ListAllScriptActions();
            }
            _completionToken.Dispose();
        }

#endregion

#region Helpers

        private void ListAllScriptActions()
        {
            _console.WriteLine(HELP_MOREINFO);
            foreach (var _scriptAction in ScriptActionsManager.ScriptActions)
            {
                if (_scriptAction.ScriptActionMeta.UnListed) continue; 
                _console.Write(PadOrConstrainString(_scriptAction.ScriptActionMeta.Prefix.ToUpper(), 16));
                _console.WriteLine(ConstrainString(_scriptAction.ScriptActionMeta.ShortDescription, 64));
            }
            _console.WriteLine();
            _console.WriteLine(HELP_MOREONLINE);
        }

        private static string PadOrConstrainString(string value, int length)
        {
            if (string.IsNullOrEmpty(value)) value = string.Empty;
            if (value.Length > length) return ConstrainString(value, length);

            // we add 
            var _addedLength = length - value.Length;
            for (var i = 0; i < _addedLength; i++)
            {
                value += SPACE;
            }
            return value;
        }

        private static string ConstrainString(string value, int length)
        {
            if (string.IsNullOrEmpty(value)) return string.Empty;
            return value.Length > length ? value.Substring(0, length - 3) + ECLIPSE : value;
        }

#endregion

    }
}
